package battle_system

import (
	"confs/gen/common"
	"game/app/actors/schemas"
	"game/app/systems/math_system/math_utils"
	"game/app/systems/move_system"
	"math/rand"

	"gitlab.outer.staruniongame.com/share/agent-common/logger"
)

// BattleBehaviorEntity
type BattleBehaviorEntity struct{}

type IBattleBehaviorEntity interface {
	OnDamage(state *schemas.MoveState, first *schemas.BattleEntity, second *schemas.BattleEntity, battle *schemas.Battle, damage int32)
	CalDamage(state *schemas.MoveState, entity *schemas.BattleEntity) int32
}

var BattleBehaviEntity IBattleBehaviorEntity = BattleBehaviorEntity{}

// CalDamage 计算伤害
func (s BattleBehaviorEntity) CalDamage(state *schemas.MoveState, entity *schemas.BattleEntity) int32 {
	return 1
}

// OnDamage 产生伤害
func (s BattleBehaviorEntity) OnDamage(state *schemas.MoveState, first *schemas.BattleEntity, second *schemas.BattleEntity, battle *schemas.Battle, damage int32) {
	if first.IsDead || second.IsDead {
		return
	}

	var curPos, targetPos math_utils.Vector2D
	var collision, targetCollision math_utils.ZNumber

	if first.Type == common.BattleEntityType_BattlePlayer {
		entity := move_system.Move.FindAndUpdate(state, first.Id)
		if entity == nil {
			logger.ERR("查找A移动实体失败:", first)
			return
		}
		curPos = entity.CurPos
		collision = entity.Collision
	} else {
		curPos = first.Position
		collision = first.Collision
	}

	if second.Type == common.BattleEntityType_BattlePlayer {
		targetEntity := move_system.Move.FindAndUpdate(state, second.Id)
		if targetEntity == nil {
			logger.ERR("查找B移动实体失败:", second)
			return
		}
		targetPos = targetEntity.CurPos
		targetCollision = targetEntity.Collision
	} else {
		targetPos = second.Position
		targetCollision = second.Collision
	}

	first.Position = curPos
	second.Position = targetPos

	noticeDist := math_utils.MakeZNumberByInt32(1)
	minDist := collision.Add(targetCollision)
	minDist = minDist.Add(noticeDist)
	minDistSquare := minDist.Mul(minDist)
	if targetPos.Sub(curPos).LengthSquare().Me(minDistSquare) {
		logger.WARN("战斗回合，不在攻击范围内:", first.Id, " ", second.Id, " ", targetPos.Sub(curPos).LengthSquare(), " ", minDistSquare)
		return
	}

	totalSoldierNum := second.GetTotalSoldierNum()
	if totalSoldierNum <= 0 {
		logger.ERR("OnDamage 1")
		return
	}

	troopSoldier := second.GetTotalSoldier(rand.Intn(second.GetTotalSoldierSize()))
	if troopSoldier == nil {
		logger.ERR("OnDamage 2")
		return
	}

	soldierIds := []int32{}
	for id, soldierNum := range troopSoldier.Soldiers {
		if soldierNum > 0 {
			soldierIds = append(soldierIds, id)
		}
	}

	if len(soldierIds) <= 0 {
		logger.ERR("OnDamage 3")
		return
	}

	confId := soldierIds[rand.Intn(len(soldierIds))]
	troopSoldier.Soldiers[int32(confId)] -= damage

	second.AddLossSoldier(&common.BattleTroopSoldier{
		UserId:   troopSoldier.UserId,
		Soldiers: map[int32]int32{confId: damage},
	})

	second.AddAcumulateLossSoldier(&common.BattleTroopSoldier{
		UserId:   troopSoldier.UserId,
		Soldiers: map[int32]int32{confId: damage},
	})

	if totalSoldierNum-damage <= 0 {
		second.IsDead = true
	}

	battle.HasRoundEvent = true
	state.AddDestoryLossTroop(second.Id, second)
}
